﻿using NewsReader.Helpers;
using NewsReader.Parsers;
using System;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using Windows.Data.Xml.Dom;
using Windows.Web.Syndication;

namespace NewsReader.ViewModels
{
    public sealed class FeedItem : INotifyPropertyChanged
    {
        public static readonly string ERROR_STRING = "Could not load article text, please try again later.";
        public event PropertyChangedEventHandler PropertyChanged;

        private readonly String _title;
        private readonly Uri _link;
        private readonly Uri _imageUri;
        private readonly DateTimeOffset _publishedDateTime;

        private SyndicationItem _si;
        private String _summary;
        private bool _fulltextLoaded;
        private String _fullText;
        private String _fullTextError;
        private DateTime? _loadedTime;
        private readonly string _feedId;
        private Task<string> _loadTextTask;


        public FeedItem(String feedId, String title, String summary, String uri, String image_uri, String fullText, DateTimeOffset publishedTime)
        {
            _feedId = feedId;
            _title = title;
            _summary = summary;
            _link = new Uri(uri);
            if (!string.IsNullOrEmpty(image_uri))
            {
                _imageUri = new Uri(image_uri);
            }
            _fullText = fullText;
            _fulltextLoaded = fullText != null;
            _publishedDateTime = publishedTime;
        }

        public FeedItem(SyndicationItem si)
        {
            _feedId = si.Id;
            _si = si;
            _title = si.Title.Text;
            _summary = si.Summary.Text;

            var doc = si.GetXmlDocument(SyndicationFormat.Rss20);
            var nodes = doc.DocumentElement.GetElementsByTagName("content");
            if (nodes.Length > 0)
            {
                var node = (XmlElement)nodes.First();
                var typeAttr = (XmlAttribute)node.Attributes.GetNamedItem("type");
                if (typeAttr != null && typeAttr.Value.Equals("image/jpeg"))
                {
                    typeAttr = (XmlAttribute)node.Attributes.GetNamedItem("url");
                    if (typeAttr != null)
                    {
                        _imageUri = new Uri(typeAttr.Value);
                    }
                }
            }
            _publishedDateTime = si.PublishedDate;

            if (si.Links.Count > 0)
            {
                _link = si.Links[0].Uri;
            }
        }

        public void LoadFullText()
        {
            try
            {
                var fullText = Parser.GetParser(SettingsManager.Instance.GetValue<string>(SupportedSettings.ParserEngine)).GetFormattedArticle(_link);
                SetFullTextFromJSON(fullText).Wait();
            }
            catch
            {
                FullTextLoaded = false;
            }
        }

        private Task SetFullTextFromJSON(string fullText)
        {
            return Task.Factory.StartNew(() =>
            {
                FullText = Parser.GetParser(SettingsManager.Instance.GetValue<string>(SupportedSettings.ParserEngine)).Parse(fullText);
                FullTextLoaded = !string.IsNullOrEmpty(FullText) && FullText != ERROR_STRING;
                
            });
        }

        public async Task LoadFullTextAsync()
        {
            try
            {
                if (FullText == ERROR_STRING)
                    FullText = null;

                _loadTextTask = Parser.GetParser(SettingsManager.Instance.GetValue<string>(SupportedSettings.ParserEngine)).GetFormattedArticleAsync(_link).AsTask();
                var fullText = await _loadTextTask;
                await SetFullTextFromJSON(fullText);
            }
            catch (Exception ex)
            {
                FullText = ERROR_STRING;
                FullTextError = ex.Message;
                FullTextLoaded = false;
            }
        }

        public string Id
        {
            get { return _feedId; }
        }

        public String Title
        {
            get { return _title; }
        }

        public Uri Link
        {
            get { return _link; }
        }


        public String Summary
        {
            get { return _summary; }
        }

        public DateTimeOffset PublishedTime
        {
            get { return _publishedDateTime; }
        }


        public Uri ImageUri
        {
            get { return _imageUri; }
        }

        public bool ImageUriExists
        {
            get { return _imageUri != null; }
        }

        public String FullText
        {
            get { return _fullText; }
            set { this.ViewModelPropertyChanged("FullText", value, ref _fullText, PropertyChanged); }
        }

        public String FullTextError
        {
            get { return _fullTextError; }
            set { this.ViewModelPropertyChanged("FullTextError", value, ref _fullTextError, PropertyChanged); }
        }

        public bool FullTextLoaded
        {
            get { return _fulltextLoaded; }
            set { this.ViewModelPropertyChanged("FullTextLoaded", value, ref _fulltextLoaded, PropertyChanged); }
        }

        public DateTime? LoadedTime
        {
            get { return _loadedTime; }
            set { this.ViewModelPropertyChanged("LoadedTime", value, ref _loadedTime, PropertyChanged); }
        }

        public Task<string> GetLoadFullTextTask()
        {
            if (_loadTextTask == null)
            {
                var tcs = new TaskCompletionSource<string>();
                tcs.SetResult(null);
                return tcs.Task;
            }
            else
            {
                return _loadTextTask;
            }
        }
    }
}
